package math.region;

import math.math;
import math.vec2;
import math.vec3;

public class Circle3 implements Surface3
{
    
    public vec3 mOrig;
    
    public vec3 mNorm;
    
    public double mRadius;
    
    
    public Circle3()
    {
        this.mOrig = new vec3();
        this.mNorm = vec3.AXIS_ZP.copy();
        this.mRadius = 0.0;
    }
    
    public Circle3(
            vec3 aOrig, 
            vec3 aNorm, 
            double aRadius)
    {
        this();
        this.set(aOrig, aNorm, aRadius);
    }
    
    
    public final void set(
            vec3 aOrig, 
            vec3 aNorm, 
            double aRadius)
    {
        this.mOrig.set(aOrig);
        this.setNormal(aNorm);
        this.mRadius = aRadius;
    }
    
    public final void set(Circle3 aOther)
    {
        this.set(aOther.mOrig, aOther.mNorm, aOther.mRadius);
    }
    
    public final void setNormal(vec3 aNorm)
    {
        this.mNorm.set(aNorm);
        this.mNorm.norm();
    }
    
    
    public boolean onSurface(vec3 aPoint)
    {
        vec3 toPt = vec3.sub(aPoint, this.mOrig);
        
        double distSq = toPt.lengthSq();
        double radSq = this.mRadius * this.mRadius;
        boolean inSphere = (distSq <= radSq);
        
        toPt.norm();
        double dot = toPt.dot(this.mNorm);
        boolean onPlane = (math.abs(dot) < math.EPSILON);
        
        return (inSphere && onPlane);
    }
    
    
    public double surfaceArea()
    {
        return (math.PI * this.mRadius * this.mRadius);
    }
    
    
    public vec3 surfaceNorm(
            vec3 aPoint, 
            vec3 aReferencePt)
    {
        vec3 localRefPt = vec3.sub(aReferencePt, this.mOrig);
        boolean onNormSide = (localRefPt.dot(this.mNorm) >= 0.0);
        if (onNormSide)
        {
            return this.mNorm.copy();
        }
        return vec3.mul(-1, this.mNorm);
    }
    
    public vec3 convertParam_World(vec2 aUV)
    {
        
        return null;
    }
    
    public vec2 convertWorld_Param(vec3 aPos)
    {
        
        return null;
    }
    
    
    public Surface3 lerp(Surface3 next, double t)
    {
        return null;
    }
    
    
    public AABB3 boundingBox()
    {
        return null;
    }
    
    
    public Circle3 copy()
    {
        Circle3 copy = new Circle3();
        copy.set(this);
        return copy;
    }
    
    
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("Circle3:\n   Orig: ");
        sb.append(this.mOrig);
        sb.append("\n   Norm: ");
        sb.append(this.mNorm);
        sb.append("\n   Radius: ");
        sb.append(this.mRadius);
        return sb.toString();
    }
    
}
